package qc.module.qms.service.producer;

import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.constants.QmsMQConstant;
import qc.common.core.enums.qms.QmsDataFlowOperateTypeEnum;
import qc.common.core.enums.qms.QmsPointTimeSegmentEnum;
import qc.common.core.utils.IdentifierUtil;
import qc.common.core.utils.LocalDateTimeUtil;
import qc.module.qms.dto.mq.QmsMqDataFlowLogMessageDto;
import qc.module.qms.service.log.QmsLogDataflowService;

import java.time.LocalDateTime;

/**
 * QMS数据流程日志发送至MQ生产者Producer，只管发送消息，不管消息是否发送至MQ
 *
 * @author QuCheng Tech
 * @since 2025/8/19
 */
@Service
public class QmsDataFlowLogProducer {
    private static final Logger logger = LoggerFactory.getLogger(QmsDataFlowLogProducer.class);

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private QmsLogDataflowService logDataflowService;

    /**
     * 消息队列中数据流程日志主题名称
     */
    private static final String MQ_Log_Topic = QmsMQConstant.MQ_LOG_DATAFLOW_TOPIC;

    /**
     * 发送原始数据流程日志消息，原始数据接收或重新处理等操作，没有点号信息
     *
     * @param nodeid    当前节点ID
     * @param flowid    流程全局ID
     * @param optype    操作类型
     * @param ismanual  是否为人工操作，人工进行重新处理
     * @param begintm   流程节点开始时间
     * @param endtm     流程节点结束时间，可以为空
     * @param issuccess 流程节点是否成功
     * @param result    流程节点运行结果信息
     * @return void
     * @author QuCheng Tech
     * @since 2025/10/9
     */
    public void sendRawDataFlowLog(String nodeid, String flowid, QmsDataFlowOperateTypeEnum optype, boolean ismanual,
                                   LocalDateTime begintm, LocalDateTime endtm, boolean issuccess, String result) {
        send(nodeid, flowid, null, optype, ismanual, begintm, endtm, issuccess, result, null, null, null, null);
    }

    /**
     * 发送数据流程日志消息
     *
     * @param nodeid       当前流程节点ID，为空时自动生成
     * @param flowid       全局流程ID，为空时同当前节点ID
     * @param fromnodeid   来源流程节点，可以为可空，为空表示本节点为全局流程的起始
     * @param optype       操作类型：原始数据接收、数据计算、数据预警、数据转发等
     * @param ismanual     是否为人工操作
     * @param begintm      流程处理的开始时间
     * @param endtm        流程处理的结束时间
     * @param issuccess    流程处理是否成功
     * @param result       流程处理结果信息
     * @param pointid      流程节点对应的点号
     * @param pointtmseg   流程节点对应的点号时段类型
     * @param pointbegintm 流程节点对应的点号数据起始时标
     * @param pointendtm   流程节点对应的点号数据截止时标
     * @return void
     * @author QuCheng Tech
     * @since 2025/10/9
     */
    public void send(String nodeid, String flowid, String fromnodeid,
                     QmsDataFlowOperateTypeEnum optype, boolean ismanual,
                     LocalDateTime begintm, LocalDateTime endtm, boolean issuccess, String result,
                     String pointid, QmsPointTimeSegmentEnum pointtmseg, LocalDateTime pointbegintm, LocalDateTime pointendtm) {
        LocalDateTime now = LocalDateTimeUtil.getNow();

        QmsMqDataFlowLogMessageDto logMsg = new QmsMqDataFlowLogMessageDto();
        //节点ID如果有传入使用传入ID，如果为空则自动生成
        if (StringUtils.isNotBlank(nodeid))
            logMsg.setNodeid(nodeid);
        else
            logMsg.setNodeid(IdentifierUtil.simpleUUID());

        //全局ID和来源节点ID使用消息上下文中的全局ID，节点ID自动生成
        logMsg.setFlowid(flowid);
        logMsg.setFromnodeid(fromnodeid);
        //数据流程操作类型：原始数据触发计算，非人工操作
        logMsg.setOptype(optype);
        logMsg.setIsmanual(ismanual);
        //如果没有指定处理起止时间使用当前时间
        logMsg.setBegintm(begintm == null ? now : begintm);
        logMsg.setEndtm(endtm == null ? now : endtm);
        //默认数据流程日志中的是否成功
        logMsg.setIssuccess(issuccess);
        //设置处理结果说明
        logMsg.setOpresult(result);
        //如果点号、点号起止时间为空保持为空
        if (StringUtils.isNotBlank(pointid)) {
            logMsg.setPointid(pointid);
            logMsg.setPointtmseg(pointtmseg);
            if (pointbegintm != null)
                logMsg.setPointbegintm(pointbegintm);
            if (pointendtm != null)
                logMsg.setPointendtm(pointendtm);
        }

        //发送数据流程日志消息
        send(logMsg);
    }

    /**
     * 向消息队列中发送监测系统数据流程处理日志消息
     * 发送日志消息不返回结果，发送错误或异常也不报错
     *
     * @param message 日志消息
     * @return void
     * @author QuCheng Tech
     * @since 2025/8/20
     */
    void send(QmsMqDataFlowLogMessageDto message) {
        try {
            logger.debug("send " + message.getOptype().toString(), message);
            //日志消息发送可以考虑使用异步发送，暂时不使用异步发送方便获取结果
            SendResult sendResult = rocketMQTemplate.syncSend(MQ_Log_Topic, message);
            SendStatus sendStatus = sendResult.getSendStatus();
            //根据发送至消息队列的结果进行判断，如果发送成功则返回成功（后续的数据处理和保存至数据库均由对应消费者进行），如果发送失败则需要再次直接调用保存到数据库方法
            if (sendStatus == SendStatus.SEND_OK) {

            } else {
                //发送失败也记录日志，直接将流程日志写入到数据库中
                logDataflowService.addLog(message);
            }
        } catch (Exception ex) {
            logger.error("发送QMS流程日志消息至MQ异常，" + ex.getMessage());
        }
    }
}
